// 协议定制
// 只有确定协议才能规定通信双方的规则

#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <jsoncpp/json/json.h>
#include "Util.hpp"

// #define MYSELF 1//用于配合条件编译使用，如果定义了该变量则使用自己的实现的序列化

namespace Protocol_ns
{
#define SEP " " // 分隔符
#define LEN strlen(SEP)
#define HEAD_SEP "\r\n"
#define HEAD_SEP_LEN strlen(HEAD_SEP)

    // 增加报头的目的是区分每一个报文的收尾，使得接收到的有效载荷是一个完整的数据
    std::string AddHeader(const std::string &str) // 增加报头
    {
        std::cout << "AddHeader 之前:\n"
                  << str << std::endl;
        std::string s = std::to_string(str.size());
        s += HEAD_SEP;
        s += str;
        s += HEAD_SEP;
        std::cout << "AddHeader 之后:\n"
                  << s << std::endl;
        return s;
    }
    std::string RemoveHeader(const std::string &str, int len) // 去除报文首尾
    {
        std::cout << "RemoveHeader 之前:\n"
                  << str << std::endl;
        std::string ret = str.substr(str.size() - HEAD_SEP_LEN - len, len);

        std::cout << "RemoveHeader 之后:\n"
                  << ret << std::endl;
        return ret; // 返回有效载荷
    }

    int ReadPackage(int sock, std::string &inbuffer, std::string *package)
    // inbuffer是一个输入输出型参数，为字节流
    // package是一个输出型参数，为从字节流中提取的一个报文
    // 返回有效载荷长度
    {
        std::cout << "ReadPackage inbuffer 之前:\n"
                  << inbuffer << std::endl;
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0); // 从网络中读取字节流，减1是为了避免访问越界
        if (s <= 0)                                            // 没有读到字节流
            return -1;
        buffer[s] = 0; // 在末尾加上结束字符串\0以便后续处理
        inbuffer += buffer;

        std::cout << "ReadPackage inbuffer 之中:\n"
                  << inbuffer << std::endl;

        // 分析报头首尾    假设一个完整报文格式如下："7"\r\n"10 + 20"\r\n
        auto pos = inbuffer.find(HEAD_SEP);
        if (pos == std::string::npos) // 如果一个\r\n都没有则返回
        {
            cout << "can not find SEP" << endl;
            return 0;
        }

        std::string lenStr = inbuffer.substr(0, pos); // 获取头部字符串"7"
        int len = Util::toInt(lenStr);                // 有效载荷长度7
        cout << "get aviliable length:" << len << endl;
        int targetPackageLen = lenStr.size() + len + 2 * HEAD_SEP_LEN; // 整个报文的长度

        if (inbuffer.size() < targetPackageLen)
            return 0;
        *package = inbuffer.substr(0, targetPackageLen); // 提取整个报文
        inbuffer.erase(0, targetPackageLen);             // 从接受的字节流中移除整个报文

        std::cout << "ReadPackage inbuffer 之后:\n"
                  << inbuffer << std::endl;
        return len;
    }

    class Request // 客户端请求
    {
    public:
        Request()
        {
        }

        Request(int x, int y, char op)
            : _x(x), _y(y), _op(op)
        {
        }

        bool Serialization(std::string *outstr) // 序列化,将结构化数据转换为网络中传输的字符串数据
        {
            *outstr = "";
#ifdef MYSELF
            std::string x_string = std::to_string(_x);
            std::string y_string = std::to_string(_y);

            // 手动序列化
            *outstr = x_string + SEP + _op + SEP + y_string;
            std::cout << "Request Serialize:\n"
                      << *outstr << std::endl;
#else
            cout << "使用Json进行序列化" << endl;
            Json::Value root; // Value是一种万能对象，接收任意kv类型

            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::FastWriter writer; // 用于进行序列化struct->string
            // Json::StyledWriter writer;
            *outstr = writer.write(root);

#endif
            return true;
        }

        bool Deserialization(const std::string &instr) // string->struct
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(instr, SEP, &result);
            if (result.size() != 3)
                return false;
            if (result[1].size() != 1)
                return false;
            _x = Util::toInt(result[0]);
            _y = Util::toInt(result[2]);
            _op = result[1][0];
#else

            Json::Value root;
            Json::Reader reader; // 用于进行反序列化
            reader.parse(instr, root);

            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
#endif
            Print();
            return true;
        }

        void Print()
        {
            std::cout << "_x: " << _x << std::endl;
            std::cout << "_y: " << _y << std::endl;
            std::cout << "_z: " << _op << std::endl;
        }

        ~Request()
        {
        }

    public:
        int _x;
        int _y;
        char _op; // 运算符
    };

    class Response // 服务端响应
    {
    public:
        Response()
        {
        }

        Response(int result, int code)
            : _result(result), _code(code)
        {
        }

        bool Serialization(std::string *outstr) // 序列化,将结构化数据转换为网络中传输的字符串数据
        {
            *outstr = "";
#ifdef MYSELF
            std::string x_string = std::to_string(_result);
            std::string y_string = std::to_string(_code);

            // 手动序列化
            *outstr = x_string + SEP + y_string;
            std::cout << "Response Serialize:\n"
                      << *outstr << std::endl;

#else
            cout << "使用Json进行序列化" << endl;
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            Json::FastWriter writer;
            // Json::StyledWriter writer;

            *outstr = writer.write(root);
#endif
            return true;
        }

        bool Deserialization(const std::string &instr) // string->struct
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(instr, SEP, &result);
            if (result.size() != 2)
                return false;

            _result = Util::toInt(result[0]);
            _code = Util::toInt(result[1]);
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(instr, root);
            _result = root["result"].asInt();
            _code = root["code"].asInt();
#endif
            Print();
            return true;
        }

        void Print()
        {
            std::cout << "_result: " << _result << std::endl;
            std::cout << "_code: " << _code << std::endl;
        }

        ~Response()
        {
        }

    public:
        int _result; // 运算结果
        int _code;   // 错误码，用户输入表达式的合法性
    };
}